from codecs import lookup
from math import log
import sys
import os
import json
import configparser
from PyQt5.QtWidgets import (QApplication, QWidget, QLabel, QComboBox, 
                             QLineEdit, QPushButton, QRadioButton, QButtonGroup,
                             QVBoxLayout, QHBoxLayout, QMainWindow, QFileDialog)  # 新增 QFileDialog 导入
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt
import open_ppt
import deal_ppt
from ui_builder import UIBuilder  # 新增导入
from logger import logger  # 新增：导入日志模块

class PPTBuilder(QWidget):
    def __init__(self):
        super().__init__()
        self.pre_configs = []
        self.config = None
        self.load_pre_configs()
        self.load_config()
        self.init_ui()  # 调用分离后的UI构建

    def load_pre_configs(self):
        """加载预设配置（兼容开发环境与打包环境）
        
        从`pre_config`目录读取所有JSON预设文件，处理解析异常并记录警告。
        """
        # 统一使用外部路径（与exe同级的pre_config目录）
        pre_config_dir = os.path.join(os.path.dirname(sys.executable), 'pre_config') if getattr(sys, 'frozen', False) else os.path.join('pre_config')
        # 开发环境保留相对路径，打包环境使用exe同级路径
        self.pre_configs = []
        
        if not os.path.exists(pre_config_dir):
            logger.warning(f"pre_config目录不存在：{pre_config_dir}")  # 替换print为日志记录
            return
        
        for filename in os.listdir(pre_config_dir):
            if filename.endswith('.json'):
                file_path = os.path.join(pre_config_dir, filename)
                try:
                    with open(file_path, 'r', encoding='utf-8') as f:
                        config = json.load(f)
                        self.pre_configs.append(config)
                except json.JSONDecodeError:
                    logger.warning(f"警告：JSON文件解析失败：{file_path}")
                except Exception as e:
                    logger.warning(f"警告：加载配置文件失败：{file_path}，错误：{e}")
        pre_config_num = len(self.pre_configs)
        logger.info(f"已加载{pre_config_num}个预设")

    def load_config(self):
        """加载配置（保持原有逻辑）"""
        self.config = configparser.ConfigParser()
        # 修改为外部路径（与exe同级的config目录）
        config_path = os.path.join(os.path.dirname(sys.executable), 'config', 'app.ini') if getattr(sys, 'frozen', False) else os.path.join('config', 'app.ini')
        # 开发环境保留相对路径，打包环境使用exe同级路径
        
        if not os.path.exists(config_path):
            self.config['DEFAULT'] = {
                'class_name': '',
                'mode': '0',
                'open_method': 'wps'
            }
            return
        
        # 常见编码列表（按优先级排序）
        encodings = ['utf-8', 'gbk', 'cp1252', 'latin-1']
        for encoding in encodings:
            try:
                self.config.read(config_path, encoding=encoding)
                logger.info(f"成功使用编码 {encoding} 读取配置文件")
                return
            except UnicodeDecodeError:
                continue  # 尝试下一个编码
        
        # 所有编码均失败时提示
        logger.error(f"错误：无法使用以下编码读取 {config_path}：{encodings}")

    def save_config(self):
        # 显式指定utf-8编码保存，避免中文乱码
        with open('config/app.ini', 'w', encoding='utf-8') as f:
            self.config.write(f)

    def init_ui(self):
        """使用分离的UI构建器初始化界面"""
        main_layout = UIBuilder.build_ui(self, self.pre_configs, self.config)
        self.setLayout(main_layout)
        
        # 窗口基础设置（保持原有逻辑）
        self.setWindowTitle('班会PPT构建器')
        self.setGeometry(300, 300, 400, 250)
        icon_path = os.path.join(
            os.path.dirname(sys.executable), 'config', 'favicon.ico'
        ) if getattr(sys, 'frozen', False) else 'config/favicon.ico'
        self.setWindowIcon(QIcon(icon_path))

    def select_target_file(self):
        """打开文件对话框选择目标PPT文件"""
        file_path, _ = QFileDialog.getOpenFileName(
            self, 
            "选择目标PPT文件", 
            os.getcwd(), 
            "PPTX文件 (*.pptx)"
        )
        if file_path:
            self.target_file_input.setText(file_path)  # 更新文件路径显示

    def generate_ppt(self):
        """生成PPT（调整无预设模式处理）"""
        try:
            class_name = self.class_input.text()
            mode = str(self.mode_group.checkedId())
            logger.info("开始执行PPT生成流程")  # 新增：记录INFO日志
            
            # 无预设时使用新添加的输入控件
            if not self.pre_configs:
                template_path = self.target_file_input.text()
                target = self.replace_target_input.text()
                if not template_path or not target:
                    logger.error("用户未提供模板路径或替换目标")  # 新增：记录ERROR日志
                    raise ValueError("请选择目标文件并输入替换目标")
                logger.info(f"无预设模式：模板路径={template_path}, 替换目标={target}")  # 新增：记录INFO日志
            else:
                # 原有预设处理逻辑
                template_index = self.template_combo.currentIndex()
                preset = self.pre_configs[template_index]
                base_dir = preset.get("pre_config_file_path", "pre_config_file")
                template_file = preset["pre_config_files"][0]
                base_path = os.path.dirname(sys.executable) if getattr(sys, 'frozen', False) else os.getcwd()
                template_path = os.path.join(base_path, base_dir, template_file)
                target = preset["target"]

            # 通用处理逻辑（保持原有）
            if not os.path.exists(template_path):
                logger.error(f"模板文件不存在：{template_path}")  # 新增：记录ERROR日志
                raise FileNotFoundError(f"模板文件不存在：{template_path}")
            logger.warning(f"注意：模板文件路径验证通过（{template_path}）")  # 新增：记录WARN日志

            deal_ppt.edit_ppt(template_path, target, class_name, int(mode))
            logger.info("PPT内容编辑完成")  # 新增：记录INFO日志
            
            # 打开PPT（保持原有逻辑）
            ppt_path = os.path.join(
                os.path.dirname(sys.executable), 'running', 'running.pptx'
            ) if getattr(sys, 'frozen', False) else os.path.abspath('running/running.pptx')
            if self.open_group.checkedId() == 0:  # WPS
                open_ppt.open_ppt(ppt_path)
            else:  # 默认程序
                open_ppt.open_ppt_with_default_app(ppt_path)
                
        except Exception as e:
            logger.error(f"生成PPT失败: {e}", exc_info=True)  # 新增：记录ERROR日志（含堆栈）
            logger.error(f"生成PPT失败: {e}")

    def save_settings(self):
        self.config['DEFAULT']['class_name'] = self.class_input.text()
        self.config['DEFAULT']['mode'] = str(self.mode_group.checkedId())
        self.config['DEFAULT']['open_method'] = 'wps' if self.open_group.checkedId() == 0 else 'default'
        logger.info("已保存设置")
        self.save_config()

    # 新增：窗口关闭事件处理
    def closeEvent(self, event):
        self.save_settings()
        """窗口关闭时删除 running/running.pptx"""
        ppt_path = os.path.abspath(os.path.join('running', 'running.pptx'))
        if os.path.exists(ppt_path):
            try:
                os.remove(ppt_path)
                logger.info(f"已删除临时文件：{ppt_path}")
            except Exception as e:
                logger.error(f"删除临时文件失败：{e}")
        super().closeEvent(event)  # 调用父类方法完成窗口关闭

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = PPTBuilder()
    ex.show()
    sys.exit(app.exec_())